package system

import (
	"github.com/gin-gonic/gin"
	"regexp"
	"ruoyi-go/internal/core/auth"
	"ruoyi-go/internal/core/constants"
	"ruoyi-go/internal/framework/utils/arrays"
	"ruoyi-go/internal/framework/utils/rest"
	"ruoyi-go/internal/web/system/domain"
	"ruoyi-go/internal/web/system/domain/vo"
	"ruoyi-go/internal/web/system/service"
	"strings"
)

func RegisterWebLoginRouter(g *gin.Engine) {
	// 登录
	g.POST("/login", func(c *gin.Context) { // 登录
		var req struct {
			Username string `json:"username" form:"username" binding:"required"`
			Password string `json:"password" form:"password" binding:"required"`
			Code     string `json:"code" form:"code" binding:"required"`
			Uuid     string `json:"uuid" form:"uuid" binding:"required"`
		}
		if err2 := c.ShouldBind(&req); err2 != nil {
			rest.Fail(err2).Send(c)
			return
		}
		token, err := service.Login(req.Username, req.Password, req.Code, req.Uuid)
		if err != nil {
			rest.Fail(err).Send(c)
			return
		}
		rest.Success().With(constants.TOKEN, token).Send(c)
	})

	// 登出
	g.POST("/logout", func(context *gin.Context) {
		auth.DeleteLoginUser(context)
		rest.Success().Send(context)
	})

	// 查询当前登录信息
	g.GET("/getInfo", func(context *gin.Context) {
		loginUser := auth.GetLoginUser(context)

		// 角色集合
		roles := service.GetRolePermissions(loginUser.User)
		// 权限集合
		permissions := service.GetMenuPermissions(loginUser.User)

		// 如果当前用户的权限发生变化
		if !arrays.Equals(loginUser.Permissions, permissions) {
			loginUser.Permissions = permissions
			auth.RefreshToken(loginUser)
		}
		rest.Success().With("user", loginUser.User).
			With("roles", roles).
			With("permissions", permissions).
			Send(context)
	})

	// 查询路由列表
	g.GET("/getRouters", func(context *gin.Context) {
		loginUser := auth.GetLoginUser(context)
		menus := service.SelectMenuTreeByUserId(loginUser.UserID)
		// 转为前端需要的格式
		builds := buildMenus(menus)
		rest.Success(builds).Send(context)
	})
}

func buildMenus(menus []*domain.SysMenu) []*vo.RouterVo {
	routers := make([]*vo.RouterVo, 0)

	for _, menu := range menus {
		router := &vo.RouterVo{}
		router.Hidden = menu.Visible == "1"
		router.Name = getRouteName(menu)
		router.Path = getRouterPath(menu)
		router.Component = getComponent(menu)
		router.Query = menu.Query
		router.Meta = &vo.MetaVo{
			Title:   menu.MenuName,
			Icon:    menu.Icon,
			NoCache: menu.IsCache == "1",
			Link:    menu.Path,
		}

		if len(menu.Children) > 0 && menu.MenuType == constants.TYPE_DIR {
			router.AlwaysShow = true
			router.Redirect = "noRedirect"
			router.Children = buildMenus(menu.Children)
		} else if isMenuFrame(menu) {
			router.Meta = nil
			childrenList := make([]*vo.RouterVo, 0)
			children := &vo.RouterVo{
				Path:      menu.Path,
				Component: menu.Component,
				Name:      getRouteNameWithPath(menu.RouteName, menu.Path), // Assuming you have this helper function
				Meta: &vo.MetaVo{
					Title:   menu.MenuName,
					Icon:    menu.Icon,
					NoCache: menu.IsCache == "1",
					Link:    menu.Path,
				},
				Query: menu.Query,
			}
			childrenList = append(childrenList, children)
			router.Children = childrenList
		} else if menu.ParentId == 0 && isInnerLink(menu) {
			router.Meta = &vo.MetaVo{
				Title: menu.MenuName,
				Icon:  menu.Icon,
			}

			router.Path = "/"
			childrenList := make([]*vo.RouterVo, 0)
			children := &vo.RouterVo{
				Path:      innerLinkReplaceEach(menu.Path), // Assuming you have this function
				Component: constants.INNER_LINK,
				Name:      getRouteNameWithPath(menu.RouteName, menu.Path), // Assuming you have this helper function
				Meta: &vo.MetaVo{
					Title: menu.MenuName,
					Icon:  menu.Icon,
					Link:  menu.Path,
				},
			}
			childrenList = append(childrenList, children)
			router.Children = childrenList
		}

		routers = append(routers, router)

	}
	return routers
}

func getRouteName(menu *domain.SysMenu) string {
	if isMenuFrame(menu) {
		return ""
	}
	return getRouteNameWithPath(menu.RouteName, menu.Path)
}

func getRouteNameWithPath(name, path string) string {

	routerName := name
	if routerName == "" {
		routerName = path
	}
	return strings.Title(routerName) // strings.Title for capitalization

}

func getRouterPath(menu *domain.SysMenu) string {
	routerPath := menu.Path
	if menu.ParentId != 0 && isInnerLink(menu) {
		routerPath = innerLinkReplaceEach(routerPath)
	}
	if menu.ParentId == 0 && menu.MenuType == constants.TYPE_DIR && menu.IsFrame == constants.NO_FRAME {
		routerPath = "/" + menu.Path
	} else if isMenuFrame(menu) {
		routerPath = "/"
	}
	return routerPath
}

func getComponent(menu *domain.SysMenu) string {
	component := constants.LAYOUT
	if menu.Component != "" && !isMenuFrame(menu) {
		component = menu.Component
	} else if menu.Component == "" && menu.ParentId != 0 && isInnerLink(menu) {
		component = constants.INNER_LINK
	} else if menu.Component == "" && isParentView(menu) {
		component = constants.PARENT_VIEW
	}
	return component
}

func isMenuFrame(menu *domain.SysMenu) bool {
	return menu.ParentId == 0 && menu.MenuType == constants.TYPE_MENU && menu.IsFrame == constants.NO_FRAME
}

func isInnerLink(menu *domain.SysMenu) bool {
	return menu.IsFrame == constants.NO_FRAME && isHttp(menu.Path) // Using the isHttp helper function
}

func isParentView(menu *domain.SysMenu) bool {
	return menu.ParentId != 0 && menu.MenuType == constants.TYPE_DIR
}

// Helper function to check for "http" or "https"
func isHttp(str string) bool {

	return strings.HasPrefix(str, "http://") || strings.HasPrefix(str, "https://")

}

func innerLinkReplaceEach(path string) string {
	re := regexp.MustCompile(`^(\w+):\/\/`) // Correct regex for scheme replacement
	return re.ReplaceAllString(path, "/")
}
